#include "event/EventDispatch.h"
#include "core/GarbageManager.h"


int count = 0;
class Test : public Obj
{
	int v;
public:
	Test(int x): v(x){
		printf("normal create %d\n", ++count);
	}
	Test(const Test& a){
		printf("copy create %d\n", ++count);
	}
	~Test(){
		printf("remove %d\n", --count);
	}
};

// 不手动释放的垃圾清理测试
void test1()
{
	new Test(1);
	new Test(2);
	{
		new Test(3);
		if(rand() % 2 == 1)
		{
			new Test(4);
			new Test(5);
		}
		new Test(6);
	}
}


// 调用引用不释放测试
void test2()
{
	Test* a = new Test(1);
	a->Retain();

	if(count > 50)
		a->Release();
}

// 非new对象的垃圾测试
void test3()
{
	Test a(1);
}

// vector数组外部创建
void test4()
{
	std::vector<Test> list;
	list.push_back(Test(1));
}

// vector数组内部创建
void test5()
{
	std::vector<Test> list;
	list.emplace_back(1);
}

// vector数组new创建(错误，不能以这种方式创建)
void test6()
{
	std::vector<Test*> list;
	list.push_back(new Test(6));
}

// vector数组new创建(正确)
void test7()
{
	std::vector<Test*> list;
	Test* t = new Test(6);
	list.push_back(t);
	t->Retain();
}

// vector数组new删除(正确)
void test8()
{
	std::vector<Test*> list;

	// 先加一个对象
	Test* t = new Test(6);
	list.push_back(t);
	t->Retain();		// 增加引用

	// 把这个对象删掉
	auto it = list.begin();
	(*it)->Release();	// 释放
	list.erase(it);		// 从列表内移除
}

void test9()
{
	Test* c = new Test(6);
	Test* d = c;
	{
		c->Retain();
		c->Release();
	}
	d->Release();
}


// 循环引用测试
class TestB : public Obj
{
	TestB* a = nullptr;
public:
	void addUse(TestB* v){
		v->Retain(this);
		this->a = v;
	}

	void removeUse(){
		if(this->a)
		{
			this->a->Release(this);
			this->a = nullptr;
		}
	}

	void doSomeThing(){
		puts("doSomeThing");
	}
};

void test10()
{
	TestB* a = new TestB;
	TestB* b = new TestB;

	a->addUse(b);
	b->addUse(a);

	a->doSomeThing();
	b->doSomeThing();

	a->removeUse();
	b->removeUse();
}

void test11()
{
	TestB* a = new TestB;
	TestB* b = new TestB;
	TestB* c = new TestB;
	TestB* d = new TestB;

	a->addUse(b);
	b->addUse(c);
	c->addUse(d);
	d->addUse(a);

	puts("----------------------");
	a->removeUse();
}

void test12()
{
	TestB* a = new TestB;
	TestB* b = new TestB;
	TestB* c = new TestB;
	TestB* d = new TestB;

	a->addUse(b);
	b->addUse(c);
	c->addUse(d);
	d->addUse(a);

	// 尝试从根解除引用
	c->Release();

	// b解除c的引用
	b->removeUse();

	// c被根引用
	TestB* e = c;
	e->Retain();

}

void test13()
{
	TestB* a = new TestB;
	TestB* b = new TestB;

	// a->Retain();
	// b->Retain();

	a->addUse(b);
	b->addUse(a);

	a->doSomeThing();
	b->doSomeThing();

	a->removeUse();
	Inst(GarbageManager)->Clear(true);	// 此处若为true，b会被清除而报错，所以需要打开retain/release的注释
	printf("ljCount:%d\tlgMemory:%d\tnewCount:%d\tnewMemory:%d\n", 
			Inst(GarbageManager)->GetGarbageCount(), 
			Inst(GarbageManager)->GetGarbageMemory(),
			Inst(GarbageManager)->GetNowNewObjectCount(),
			Inst(GarbageManager)->GetNowNewObjectMemory()
		);
	b->removeUse();

	// a->Release();
	// b->Release();
}

void gc()
{
	Inst(GarbageManager)->Clear(true);
	printf("ljCount:%d\tlgMemory:%d\tnewCount:%d\tnewMemory:%d\n", 
			Inst(GarbageManager)->GetGarbageCount(), 
			Inst(GarbageManager)->GetGarbageMemory(),
			Inst(GarbageManager)->GetNowNewObjectCount(),
			Inst(GarbageManager)->GetNowNewObjectMemory()
		);
}

void test14()
{
	TestB* a = new TestB;
	a->Retain();

	{
		TestB* b = new TestB;
		b->Retain();
		b->addUse(a);
		a->addUse(b);
		b->Release();

		gc();
	}

	{
		a->doSomeThing();
		gc();
	}

	{
		a->removeUse();
		gc();
	}

	a->Release();
	gc();
}

int main(int argc,char *argv[])
{
	GarbageManager* gc = Inst(GarbageManager);

	for(int i = 0; i < 1; ++i)
	{
		test14();

		gc->update(1);
		printf("ljCount:%d\tlgMemory:%d\tnewCount:%d\tnewMemory:%d\n", 
			gc->GetGarbageCount(), 
			gc->GetGarbageMemory(),
			gc->GetNowNewObjectCount(),
			gc->GetNowNewObjectMemory()
		);
	}

	return 0;
}